package com.blue.base.common.utils.http;

import com.alibaba.fastjson.JSON;
import com.blue.base.common.exception.BaseException;
import com.blue.base.common.utils.json.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;

/**
 * @author liulei
 * @version 2.0
 */
@Slf4j
@Configuration
public class RestTemplateUtil<K, V> {
    public static RestTemplate restTemplate;

    @PostConstruct
    public void init() {
        restTemplate = new RestTemplate(clientHttpRequestFactory());
    }

    @Bean
    public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        //开始设置连接池
        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager
                = new PoolingHttpClientConnectionManager();
        //最大连接数
        poolingHttpClientConnectionManager.setMaxTotal(100);
        //同路由并发数
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(20);
        httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);

        HttpClient httpClient = httpClientBuilder.build();
        // httpClient连接配置
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory
                = new HttpComponentsClientHttpRequestFactory(httpClient);
        //连接超时
        clientHttpRequestFactory.setConnectTimeout(30 * 1000);
        //数据读取超时时间
        clientHttpRequestFactory.setReadTimeout(60 * 1000);
        //连接不够用的等待时间
        clientHttpRequestFactory.setConnectionRequestTimeout(30 * 1000);
        return clientHttpRequestFactory;
    }


    /**
     * post请求
     *
     * @param url    请求地址
     * @param param  参数对象
     * @param target 返回目标类
     * @param <V>    目标泛型
     * @return 目标泛型对象
     */
    public <V> V post(String url, Object param, HttpHeaders headers, Class<V> target) {
        HttpEntity requestEntity = new HttpEntity(param, headers);
        ResponseEntity<V> remoteResult = restTemplate.postForEntity(url, requestEntity, target);
        if (remoteResult.getStatusCodeValue() != HttpStatus.SC_OK) {
            throw new BaseException(10000, "Post接口远程调用异常");
        }
        return remoteResult.getBody();
    }

    /**
     * 带返回值的调用
     *
     * @param url         请求地址
     * @param param       参数对象
     * @param targetClass 目标泛型类
     * @param <V>         目标泛型
     * @return
     */
    public static <V> V post(String url, Object param, Class<V> targetClass) {
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Object> request = new HttpEntity<>(param, requestHeaders);
        log.info("meter|remote|invoke|param|{}|{}", url, JSON.toJSONString(param));
        ResponseEntity<V> remoteResult;
        try {
            remoteResult = restTemplate.postForEntity(url, request, targetClass);
        } catch (Exception e) {
            log.error("restTemplate|remote|invoke|system|error|", e);
            throw new BaseException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "远程调用异常");
        }
        if (remoteResult.getStatusCodeValue() != HttpStatus.SC_OK) {
            log.error("restTemplate|remote|invoke|business|error|{}", JSON.toJSONString(remoteResult));
            throw new BaseException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "远程调用接口出现异常，请检查系统");
        }
        log.info("restTemplate|remote|invoke|result|{}", JSON.toJSONString(remoteResult));
        if (remoteResult.getBody() == null) {
            return null;
        }
        return remoteResult.getBody();
    }

    /**
     * 接口远程调用
     *
     * @param url    url
     * @param param  参数
     * @param target 目标泛型类
     * @param <V>    目标泛型
     * @return 目标类结果
     */
    public static <V> V get(String url, Object param, Class<V> target) {
        ResponseEntity<V> remoteResult = restTemplate.getForEntity(url, target, JsonUtil.toJson(param));
        if (remoteResult.getStatusCodeValue() != HttpStatus.SC_OK) {
            throw new BaseException(20000, "Get接口远程调用异常");
        }
        return remoteResult.getBody();
    }
    /**
     * 1.结果值转对象
     * Map<String, Object> data = (Map<String, Object>) remoteResult.getBody().getData();
     * XinAoQueryMeterVO receipt = JSONObject.parseObject(JSONObject.toJSONString(data), XinAoQueryMeterVO.class);
     * 2.结果值转List
     * List<Map<String, Object>> data = (List<Map<String, Object>>) remoteResult.getBody().getData();
     * List<IotRemoteStationVO> receipt = JSONObject.parseArray(JSONObject.toJSONString(data), IotRemoteStationVO.class);
     */
}
